/**
 * @file heap.c
 * @author LokLiang (lokliang@163.com)
 * @brief
 * @version 0.1
 * @date 2023-05-01
 *
 * @copyright Copyright (c) 2023
 *
 */

#include "heap.h"
#include "sys_log.h"

#if !defined(CONFIG_MEMM_TYPE) || (CONFIG_MEMM_TYPE == 1)
#include "memm1.c"
#else
#include "memm2.c"
#endif

#define LIST_NODE_TYPE CONFIG_MEMM_NODE_TYPE
#include "list/dlist.h"

#if CONFIG_MEMM_NODE_TYPE == 1
#define _HEAP_GET_HANDLE_POINTER(ADDR) (void *)(*(int *)(ADDR) == 0 ? 0 : (int)(ADDR) + *(int *)(ADDR))
#define _HEAP_SET_HANDLE_POINTER(TAR, SRC)                        \
    {                                                             \
        int *int_tar = (int *)TAR;                                \
        *int_tar = ((SRC) == NULL ? 0 : (int)(SRC) - (int)(TAR)); \
    }
#else
#define _HEAP_GET_HANDLE_POINTER(ADDR) (*(void **)(ADDR))
#define _HEAP_SET_HANDLE_POINTER(TAR, SRC) (*(void **)(TAR) = (SRC))
#endif

#define _HEAP_CONTAINER_OF(PTR, TYPE, MEMBER) ((TYPE *)&((uint8_t *)PTR)[-(int)&((TYPE *)0)->MEMBER])

static void _heap_nop(void)
{
}
static heap_critical_entry_fn _heap_entry_critical = _heap_nop; // 进入临界访问
static heap_critical_exit_fn _heap_exit_critical = _heap_nop;   // 退出临界访问

heap_t g_heap_default_handle = {.handle = NULL};

static int _memcmp(const void *cs, const unsigned *ct, unsigned count)
{
    const uint8_t *cs_8 = cs;
    unsigned cnt = 0;
    int ret = 0;

    if ((int)cs % sizeof(unsigned) == 0) // 待比较数据按 sizeof(unsigned) 对齐
    {
        const unsigned *cs_int = cs;
        for (cnt = 0; cnt < count / sizeof(*ct); cnt++)
        {
            if ((ret = cs_int[cnt] - ct[cnt]) != 0)
            {
                return ret;
            }
        }
    }

    for (cnt *= sizeof(*ct); cnt < count; cnt++)
    {
        if ((ret = ((uint8_t *)cs_8)[cnt] - ((uint8_t *)ct)[cnt]) != 0)
        {
            return ret;
        }
    }

    return ret;
}

size_t _cpu_clz(size_t val)
{
#if defined(__CC_ARM)
    return __builtin_clz(val);
#elif defined(__GNUC__)
    if (val == 0)
    {
        return 32;
    }
    return __builtin_clz(val);
#else
    static uint8_t const tab[256] = {
        8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, // 0x00
        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0x10
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x20
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x30
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xB0
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xD0
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xF0
    };

    if (val > 0xFFFF)
    {
        if (val > 0xFFFFFF)
        {
            return tab[val >> 24 & 0xFF];
        }
        else
        {
            return tab[val >> 16 & 0xFF] + 8;
        }
    }
    else
    {
        if (val > 0xFF)
        {
            return tab[val >> 8 & 0xFF] + 16;
        }
        else
        {
            return tab[val & 0xFF] + 24;
        }
    }
#endif // defined(__CC_ARM)
}

__weak void _default_heap_init(void)
{
    for (;;)
    {
    }
}

void *__malloc(size_t size)
{
    return memm_malloc(g_heap_default_handle.handle, size);
}

void *__calloc(size_t nmemb, size_t size)
{
    return memm_calloc(g_heap_default_handle.handle, size);
}

void *__realloc(void *ptr, size_t size)
{
    return memm_realloc(g_heap_default_handle.handle, ptr, size);
}

void __free(void *ptr)
{
    memm_free(g_heap_default_handle.handle, ptr);
}

/**
 * @brief 设置临界函数，可不设置则
 *
 * @param entry_critical 进入临界的函数
 * @param exit_critical 退出临界的函数
 */
void heap_port_init(heap_critical_entry_fn entry_critical, heap_critical_exit_fn exit_critical)
{
    if (entry_critical)
    {
        _heap_entry_critical = entry_critical;
    }
    if (exit_critical)
    {
        _heap_exit_critical = exit_critical;
    }
}

/**
 * @brief 执行 heap_port_init() 所定义的进入临界的函数
 */
void heap_entry_critical(void)
{
    _heap_entry_critical();
}

/**
 * @brief 执行 heap_port_init() 所定义的退出临界的函数
 */
void heap_exit_critical(void)
{
    _heap_exit_critical();
}

/**
 * @brief 初始化一个内存空间为内存池
 * 对象内存 164 bytes
 *
 * @param heap_handle 堆对象 内存对象。当取值为 NULL 时，使用内部的对象指针
 * @param memm_base 内存空间地址
 * @param mem_size 内存空间大小（字节）
 * @return int 0 -- 成功, -1 -- 失败
 */
int heap_init(heap_t *heap_handle, void *memm_base, unsigned mem_size)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    if (heap_handle != &g_heap_default_handle || g_heap_default_handle.handle == NULL)
    {
        *(memm_t **)heap_handle = memm_init(memm_base, mem_size);
        if (*(memm_t **)heap_handle == NULL)
        {
            return -1;
        }
    }
    return 0;
}

/**
 * @brief 申请大小为 size 字节的连续内存空间
 *
 * @param heap_handle 堆对象 内存对象。当取值为 NULL 时，使用内部的对象指针
 * @param size 申请的空间大小（字节）
 * @return void* NULL -- 失败
 * @return void* 内存地址
 */
void *heap_malloc(heap_t *heap_handle, unsigned size)
{
    void *ret;

    if (g_heap_default_handle.handle == NULL)
    {
        _default_heap_init();
    }

    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    _heap_entry_critical();
    ret = memm_malloc(*(memm_t **)heap_handle, size);
    _heap_exit_critical();

    return ret;
}

/**
 * @brief 申请大小为 size 字节的连续内存空间并清0
 *
 * @param heap_handle 堆对象 内存对象。当取值为 NULL 时，使用内部的对象指针
 * @param size 申请的空间大小（字节）
 * @return void* NULL -- 失败
 * @return void* 内存地址
 */
void *heap_calloc(heap_t *heap_handle, unsigned size)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);
    void *ret = heap_malloc(heap_handle, size);

    if (ret != NULL)
    {
        memset(ret, 0, size);
    }
    return ret;
}

/**
 * @brief 优先从空闲块的尾部申请大小为 size 字节的连续内存空间
 *
 * @param heap_handle 堆对象 内存对象。当取值为 NULL 时，使用内部的对象指针
 * @param size 申请的空间大小（字节）
 * @return void* 内存地址
 */
void *heap_malloc_tail(heap_t *heap_handle, unsigned size)
{
    void *ret;

    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    _heap_entry_critical();
    ret = memm_malloc_tail(*(memm_t **)heap_handle, size);
    _heap_exit_critical();

    return ret;
}

/**
 * @brief 优先从空闲块的尾部申请大小为 size 字节的连续内存空间并清0
 *
 * @param heap_handle 堆对象 内存对象。当取值为 NULL 时，使用内部的对象指针
 * @param size 申请的空间大小（字节）
 * @return void* 内存地址
 */
void *heap_calloc_tail(heap_t *heap_handle, unsigned size)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    void *ret = heap_malloc_tail(heap_handle, size);

    if (ret != NULL)
    {
        memset(ret, 0, size);
    }
    return ret;
}

/**
 * @brief 重定义已申请的内存大小
 * 原数据将被复制
 * 如果新定义的内存长度小于原长度，尾部的数据将丢失
 *
 * @param heap_handle 堆对象 内存对象。当取值为 NULL 时，使用内部的对象指针
 * @param p 已申请的内存地址
 * @param size 重定义大小（字节）
 * @return void* NULL -- 失败
 * @return void* 新的内存地址
 */
void *heap_realloc(heap_t *heap_handle, void *p, unsigned size)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    void *ret = NULL;
    _heap_entry_critical();
    if (p == NULL)
    {
        ret = memm_malloc(*(memm_t **)heap_handle, size);
    }
    else
    {
        ret = memm_realloc(*(memm_t **)heap_handle, p, size);
    }
    _heap_exit_critical();

    return ret;
}

/**
 * @brief 释放已申请的内存
 *
 * @param heap_handle 堆对象 内存对象。当取值为 NULL 时，使用内部的对象指针
 * @param p 已申请的内存地址
 */
void heap_free(heap_t *heap_handle, void *p)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    _heap_entry_critical();
    memm_free(*(memm_t **)heap_handle, p);
    _heap_exit_critical();
}

/**
 * @brief 释放所有内存
 *
 * @param heap_handle 堆对象 内存对象。当取值为 NULL 时，使用内部的对象指针
 */
void heap_free_all(heap_t *heap_handle)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    _heap_entry_critical();
    memm_free_all(*(memm_t **)heap_handle);
    _heap_exit_critical();
}

/**
 * @brief 获取内存指针是否有效
 *
 * @param p 已申请的内存地址
 * @return true 有效
 * @return false 无效
 */
bool heap_is_valid(heap_t *heap_handle, void *p)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    return memm_is_valid(*(memm_t **)heap_handle, p);
}

/**
 * @brief 已申请内存块的实际占用空间大小（不含所有控制信息）
 *
 * @param p 已申请的内存地址
 * @return unsigned 已申请的内存块（不含所有控制信息）的实际大小（字节）
 */
unsigned heap_block_size(void *p)
{
    return memm_get_data_space_size(p);
}

/**
 * @brief 已申请内存块的实际占用空间大小（含所有控制信息）
 *
 * @param p 已申请的内存地址
 * @return unsigned 已申请的内存块（含所有控制信息）的实际大小（字节）
 */
unsigned heap_space_size(void *p)
{
    return memm_get_data_space_size(p) + memm_get_block_info_size();
}

/**
 * @brief 获取用户定义的内存的基地址
 *
 * @param heap_handle 堆对象
 * @return void* 户定义的内存的基地址
 */
void *heap_get_base(heap_t *heap_handle)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    return memm_get_base(*(memm_t **)heap_handle);
}

/**
 * @brief 获取用户定义的内存的结束地址
 *
 * @param heap_handle 堆对象
 * @return void* 用户定义的内存的结束地址
 */
void *heap_get_end(heap_t *heap_handle)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    return memm_get_end(*(memm_t **)heap_handle);
}

/**
 * @brief 获取总已使用空间
 *
 * @param heap_handle 堆对象
 * @return unsigned 总已使用空间（字节）
 */
unsigned heap_used_size(heap_t *heap_handle)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    return memm_used_size(*(memm_t **)heap_handle);
}

/**
 * @brief 获取总空闲空间（包含所有碎片）
 *
 * @param heap_handle 堆对象
 * @return unsigned 总空闲空间（包含所有碎片）（字节）
 */
unsigned heap_free_size(heap_t *heap_handle)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    return memm_free_size(*(memm_t **)heap_handle);
}

/**
 * @brief 获取当前最大的连续空间
 *
 * @param heap_handle 堆对象
 * @return unsigned 当前最大的可申请的空间（字节）
 */
unsigned heap_block_max(heap_t *heap_handle)
{
    unsigned ret;

    if (g_heap_default_handle.handle == NULL)
    {
        _default_heap_init();
    }

    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    _heap_entry_critical();
    ret = memm_block_max(*(memm_t **)heap_handle);
    _heap_exit_critical();

    return ret;
}

/**
 * @brief 堆的头信息消耗的字节数
 *
 * @return unsigned
 */
unsigned heap_header_size(void)
{
    return memm_get_header_info_size();
}

/**
 * @brief 每个管理块额外消耗的字节数
 *
 * @return unsigned
 */
unsigned heap_mblock_size(void)
{
    return memm_get_block_info_size();
}

/**
 * @brief 获取堆的空间信息
 *
 * @param heap_handle 堆对象
 * @param dst_used[out] 已用空间（字节）
 * @param dst_free[out] 总空闲空间（字节）
 * @param dst_max_block[out] 最连续的空闲空间（字节）
 * @return int 0 -- 成功，-1 -- 失败
 */
int heap_info(heap_t *heap_handle, size_t *dst_used, size_t *dst_free, size_t *dst_max_block)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    _heap_entry_critical();
    if (dst_used)
        *dst_used = memm_used_size(*(memm_t **)heap_handle);
    if (dst_free)
        *dst_free = memm_free_size(*(memm_t **)heap_handle);
    if (dst_max_block)
        *dst_max_block = memm_block_max(*(memm_t **)heap_handle);
    _heap_exit_critical();

    return 0;
}

#define _HEAPK_GET_HASH_LIST(memk_base, hash_value) (&((dlist_t *)&(memk_base)[1])[(hash_value) % (memk_base)->lists])

#if CONFIG_MEMM_NODE_TYPE == 1
#define _HEAPK_GET_POINTER(DevValue) ((Type_MemK_Item_Def *)(&((uint8_t *)pHdr)[DevValue]))
#define _HEAPK_GET_VALUE(Pointer) ((unsigned)(Pointer) - (unsigned)pHdr)
#else
#define _HEAPK_GET_POINTER(DevValue) (DevValue)
#define _HEAPK_GET_VALUE(Pointer) (Pointer)
#endif

typedef struct
{
    heap_t *heap_handle;
    unsigned lists;          // 确定使用多少个链头，一般按预算最大成员数量的一半取值。
    unsigned list_index;     // 逐个搜索时，当前可读出的项目序号
    dlist_node_t *list_node; // 逐个搜索时，当前可读出的项目地址
} heapk_handle_t;

typedef struct
{
    dlist_node_t node;
    heapk_handle_t *heapk_handle;
    unsigned mem_size : 24;
    unsigned key_size : 8;
} k_heapk_node_t;

/**
 * @brief 计算键值的哈希值
 *
 * @param key
 * @param size
 * @return unsigned
 */
static unsigned _heapk_gen_hash(const void *key, unsigned size)
{
    uint8_t *p8 = (uint8_t *)key;
    unsigned h = 0;

    while (size--)
    {
        h = ((h << 5) ^ (h >> 27)) ^ *p8++;
    }

    return h;
}

/**
 * @brief 获取内存指针是否有效
 *
 * @param p 已申请的内存地址
 * @return true 有效
 * @return false 无效
 */
bool _heapk_valid_state(void *p)
{
    if (p == NULL)
    {
        return false;
    }

    k_heapk_node_t *memk_node = &((k_heapk_node_t *)p)[-1];
    void *addr = &memk_node->heapk_handle;
    heapk_handle_t *memk = _HEAP_GET_HANDLE_POINTER(addr);
    if ((int)memk & 1)
    {
        return false;
    }
    if (memk_node->mem_size == 0)
    {
        return false;
    }
    addr = &memk->heap_handle;
    memm_t *memm_hdl = _HEAP_GET_HANDLE_POINTER(addr);
    if ((int)memm_hdl & 1)
    {
        return false;
    }

    return memm_is_valid(memm_hdl, memk_node);
}

/**
 * @brief 创建一个散列表
 *
 * @param heapk_handle 散列表对象
 * @param heap_handle 依赖的已初始化的堆的对象。当取值为 NULL 时，使用内部的对象指针
 * @param lists 生成多少个列表，每个列表消耗 sizeof(size_t) 个字节
 * @return int 0 -- 成功，-1 -- 失败
 */
int heapk_create(heapk_t *heapk_handle, heap_t *heap_handle, int lists)
{
    heap_handle = (heap_handle == NULL ? &g_heap_default_handle : heap_handle);

    _heap_entry_critical();
    heapk_handle_t *memk = memm_malloc(*(memm_t **)heap_handle, sizeof(heapk_handle_t) + sizeof(dlist_t) * lists);
    _heap_exit_critical();

    if (memk == NULL)
    {
        return -1;
    }
    else
    {
        dlist_t *list = _HEAPK_GET_HASH_LIST(memk, 0);
        for (int i = 0; i < lists; i++)
        {
            dlist_init_list(&list[i]);
        }
        _HEAP_SET_HANDLE_POINTER(&memk->heap_handle, *(memm_t **)heap_handle);
        memk->lists = lists;
        heapk_handle->handle = memk;
        heapk_list_reset(heapk_handle);
        return 0;
    }
}

/**
 * @brief 查询散列表依赖的堆的句柄
 *
 * @param heapk_handle 散列表对象
 * @param heap_handle[out] 输出 -- 保存散列表依赖的堆的句柄
 */
void heapk_heap_base(heapk_t *heapk_handle, heap_t *heap_handle)
{
    if (heapk_handle->handle != NULL)
    {
        heapk_handle_t *memk = heapk_handle->handle;
        void *addr = &memk->heap_handle;
        *(memm_t **)heap_handle = _HEAP_GET_HANDLE_POINTER(addr);
    }
}

/**
 * @brief 删除散列表
 *
 * @param heapk_handle 散列表对象
 */
void heapk_delete(heapk_t *heapk_handle)
{
    heapk_handle_t *memk = heapk_handle->handle;

    if (memk == NULL)
    {
        SYS_LOG_WRN("Never use 'heapk_create()' to initialize");
        return;
    }

    if (heapk_handle->handle != NULL)
    {
        heapk_free_all(heapk_handle);

        heap_t heap_handle;
        heapk_heap_base(heapk_handle, &heap_handle);
        _heap_entry_critical();
        memm_free(*(memm_t **)&heap_handle, memk);
        _heap_exit_critical();

        heapk_handle->handle = NULL;
    }
}

/**
 * @brief 在散列表中申请一个带映射键值的内存。
 *
 * @param heapk_handle 散列表对象
 * @param mem_size 申请的空间大小（字节）
 * @param key_base 映射键值的地址
 * @param key_size 映射键值的大小（字节）
 * @return void* NULL -- 失败
 * @return void* 内存地址
 */
void *heapk_malloc(heapk_t *heapk_handle, int mem_size, const void *key_base, uint8_t key_size)
{
    heapk_handle_t *memk = heapk_handle->handle;

    mem_size += !mem_size;

    if (memk == NULL)
    {
        SYS_LOG_WRN("Never use 'heapk_create()' to initialize");
        return NULL;
    }
    else if (key_size == 0)
    {
        SYS_LOG_WRN("key_size = 0");
        return NULL;
    }
    else if (heapk_block_base(heapk_handle, key_base, key_size) != NULL)
    {
        SYS_LOG_WRN("Key value is already in the list");
        return NULL;
    }
    else
    {
        _heap_entry_critical();
        void *addr = &memk->heap_handle;
        k_heapk_node_t *memk_node = memm_malloc(_HEAP_GET_HANDLE_POINTER(addr),
                                                sizeof(*memk_node) +
                                                    (mem_size + sizeof(int) - 1) / sizeof(int) * sizeof(int) +
                                                    (key_size + sizeof(int) - 1) / sizeof(int) * sizeof(int));
        _heap_exit_critical();

        if (memk_node == NULL)
        {
            return NULL;
        }
        else
        {
            _HEAP_SET_HANDLE_POINTER(&memk_node->heapk_handle, heapk_handle->handle);
            memk_node->mem_size = mem_size;
            memk_node->key_size = key_size;
            memcpy(&((uint8_t *)&memk_node[1])[(mem_size + sizeof(int) - 1) / sizeof(int) * sizeof(int)], key_base, key_size);

            _heap_entry_critical();
            dlist_init_node(&memk_node->node);
            dlist_insert_tail(_HEAPK_GET_HASH_LIST(memk, _heapk_gen_hash(key_base, key_size)), &memk_node->node);
            _heap_exit_critical();

            heapk_list_reset(heapk_handle);

            return &memk_node[1];
        }
    }
}

/**
 * @brief 只删除关键字，但所申请的内存依然保留并可用
 *
 * @param p 已申请的内存地址
 */
void heapk_clr_key(void *p)
{
    if (p == NULL)
    {
        SYS_LOG_WRN("p = NULL");
        return;
    }

    k_heapk_node_t *memk_node = &((k_heapk_node_t *)p)[-1];

    memk_node->key_size = 0;
}

/**
 * @brief 释放内存
 *
 * @param p 已申请的内存地址
 */
void heapk_free(void *p)
{
    if (p == NULL)
    {
        SYS_LOG_WRN("p = NULL");
        return;
    }

    k_heapk_node_t *memk_node = &((k_heapk_node_t *)p)[-1];
    _heap_entry_critical();
    void *addr = &memk_node->heapk_handle;
    heapk_handle_t *memk = _HEAP_GET_HANDLE_POINTER(addr);
    void *key = heapk_key_base(p);
    int key_size = heapk_key_size(p);
    dlist_remove(_HEAPK_GET_HASH_LIST(memk, _heapk_gen_hash(key, key_size)), &memk_node->node);
    memk_node->key_size = 0;
    memk_node->mem_size = 0;
    _heap_exit_critical();

    heapk_t heapk_handle;
    heapk_handle.handle = memk;
    heapk_list_reset(&heapk_handle);

    _heap_entry_critical();
    addr = &memk->heap_handle;
    memm_free(_HEAP_GET_HANDLE_POINTER(addr), memk_node);
    _heap_exit_critical();
}

/**
 * @brief 释放所有内存
 *
 * @param heapk_handle 散列表对象
 */
void heapk_free_all(heapk_t *heapk_handle)
{
    heapk_handle_t *memk = heapk_handle->handle;

    if (memk == NULL)
    {
        SYS_LOG_WRN("Never use 'heapk_create()' to initialize");
        return;
    }
    else
    {
        dlist_t *list = _HEAPK_GET_HASH_LIST(memk, 0);
        for (unsigned i = 0; i < memk->lists; i++)
        {
            while (1)
            {
                _heap_entry_critical();
                dlist_node_t *node = dlist_take_head(&list[i]);
                if (node == NULL)
                {
                    _heap_exit_critical();
                    break;
                }
                else
                {
                    void *addr = &memk->heap_handle;
                    memm_free(_HEAP_GET_HANDLE_POINTER(addr), node);
                    _heap_exit_critical();
                }
            }
        }
        heapk_list_reset(heapk_handle);
    }
}

/**
 * @brief 重置列举指针
 *
 * @param heapk_handle 散列表对象
 */
void heapk_list_reset(heapk_t *heapk_handle)
{
    heapk_handle_t *memk = heapk_handle->handle;

    if (memk == NULL)
    {
        SYS_LOG_WRN("Never use 'heapk_create()' to initialize");
        return;
    }

    _heap_entry_critical();
    memk->list_index = 0;
    _HEAP_SET_HANDLE_POINTER(&memk->list_node, 0);
    _heap_exit_critical();
}

/**
 * @brief 列举下个已申请的内存信息
 *
 * @param heapk_handle 散列表对象
 * @param store_mem_base 输出 -- 保存已申请的内存地址
 * @param store_key_base 输出 -- 保存键值的的内存地址
 * @param store_key_size 输出 -- 保存键值的的大小（字节）
 * @return true 找到信息
 * @return false 已找完所有信息
 */
bool heapk_list_next(heapk_t *heapk_handle, void **store_mem_base, void **store_key_base, uint8_t *store_key_size)
{
    heapk_handle_t *memk = heapk_handle->handle;

    if (memk == NULL)
    {
        SYS_LOG_WRN("Never use 'heapk_create()' to initialize");
        return false;
    }
    else if (memk->list_index >= memk->lists)
    {
        return false;
    }
    else
    {
        _heap_entry_critical();

        dlist_node_t *node;
        dlist_t *hash_list = _HEAPK_GET_HASH_LIST(memk, memk->list_index);
        void *addr = &memk->list_node;

        do
        {
            if (dlist_peek_tail(hash_list) == _HEAP_GET_HANDLE_POINTER(addr))
            {
                memk->list_index++;
                if (memk->list_index < memk->lists)
                {
                    hash_list = &hash_list[1];
                    _HEAP_SET_HANDLE_POINTER(&memk->list_node, dlist_peek_head(hash_list));
                }
                else
                {
                    _HEAP_SET_HANDLE_POINTER(&memk->list_node, NULL);
                    break;
                }
            }
            else if (_HEAP_GET_HANDLE_POINTER(addr) == NULL)
            {
                _HEAP_SET_HANDLE_POINTER(&memk->list_node, dlist_peek_head(hash_list));
            }
            else
            {
                _HEAP_SET_HANDLE_POINTER(&memk->list_node, dlist_peek_next(hash_list, _HEAP_GET_HANDLE_POINTER(addr)));
            }

        } while (_HEAP_GET_HANDLE_POINTER(addr) == NULL ||
                 _HEAP_CONTAINER_OF(_HEAP_GET_HANDLE_POINTER(addr), k_heapk_node_t, node)->key_size == 0);

        node = _HEAP_GET_HANDLE_POINTER(addr);

        _heap_exit_critical();

        if (_HEAP_GET_HANDLE_POINTER(addr) == NULL)
        {
            return false;
        }
        else
        {
            k_heapk_node_t *memk_node = _HEAP_CONTAINER_OF(node, k_heapk_node_t, node);
            if (store_mem_base != NULL)
            {
                *store_mem_base = &memk_node[1];
            }
            if (store_key_base != NULL)
            {
                *store_key_base = &((uint8_t *)&memk_node[1])[(memk_node->mem_size + sizeof(int) - 1) / sizeof(int) * sizeof(int)];
            }
            if (store_key_size != NULL)
            {
                *store_key_size = memk_node->key_size;
            }
            return true;
        }
    }
}

/**
 * @brief 获取内存指针是否有效
 *
 * @param p 已申请的内存地址
 * @return true 有效
 * @return false 无效
 */
bool heapk_is_valid(void *p)
{
    if (_heapk_valid_state(p) == false)
    {
        return false;
    }

    k_heapk_node_t *memk_node = &((k_heapk_node_t *)p)[-1];
    if (memk_node->key_size == 0 || memk_node->mem_size == 0)
    {
        return false;
    }

    return true;
}

/**
 * @brief 通过键值查找 heapk_malloc() 的申请的内存地址
 *
 * @param key_base 映射键值的地址
 * @param key_size 映射键值的大小（字节）
 * @return void* NULL -- 没有该键值
 * @return void* 内存地址
 */
void *heapk_block_base(heapk_t *heapk_handle, const void *key_base, uint8_t key_size)
{
    heapk_handle_t *memk = heapk_handle->handle;

    if (memk == NULL)
    {
        SYS_LOG_WRN("Never use 'heapk_create()' to initialize");
        return NULL;
    }
    else if (key_size == 0)
    {
        SYS_LOG_WRN("key_size = 0");
        return NULL;
    }
    else
    {
        _heap_entry_critical();
        dlist_t *list = _HEAPK_GET_HASH_LIST(memk, _heapk_gen_hash(key_base, key_size));
        dlist_node_t *node = dlist_peek_head(list);
        dlist_node_t *last_node = dlist_peek_tail(list);

        while (node != NULL)
        {
            k_heapk_node_t *memk_node = _HEAP_CONTAINER_OF(node, k_heapk_node_t, node);
            if (memk_node->key_size == key_size)
            {
                unsigned *p32_test_key = (unsigned *)&((uint8_t *)&memk_node[1])[(memk_node->mem_size + sizeof(int) - 1) / sizeof(int) * sizeof(int)];

                if (_memcmp(key_base, p32_test_key, key_size) == 0)
                {
                    _heap_exit_critical();
                    if (_heapk_valid_state(&memk_node[1]) == false)
                    {
                        return NULL;
                    }
                    else
                    {
                        return &memk_node[1];
                    }
                }
            }

            if (node == last_node)
            {
                node = NULL;
            }
            else
            {
                node = dlist_peek_next(list, node);
            }
        }
        _heap_exit_critical();

        return NULL;
    }
}

/**
 * @brief 通过内存封装地址获取 heapk_malloc() 申请时设定的内存大小
 *
 * @param p 已申请的内存地址
 * @return int 使用 heapk_malloc() 申请时设定的内存大小
 */
int heapk_block_size(void *p)
{
    if (_heapk_valid_state(p) == false)
    {
        return 0;
    }
    else
    {
        k_heapk_node_t *memk_node = &((k_heapk_node_t *)p)[-1];
        return memk_node->mem_size;
    }
}

/**
 * @brief 已申请内存块的实际占用空间大小（含所有控制信息）（字节）
 *
 * @param p 已申请的内存地址
 * @return int 实际占用空间大小（含所有控制信息）（字节）
 */
int heapk_space_size(void *p)
{
    if (_heapk_valid_state(p) == false)
    {
        return 0;
    }
    else
    {
        return memm_get_data_space_size(&((k_heapk_node_t *)p)[-1]) + memm_get_block_info_size();
    }
}

/**
 * @brief 通过内存封装地址获取 heapk_malloc() 申请时设定的键值地址
 *
 * @param p 已申请的内存地址
 * @return void* 键值地址
 */
void *heapk_key_base(void *p)
{
    if (_heapk_valid_state(p) == false)
    {
        return NULL;
    }
    else
    {
        k_heapk_node_t *memk_node = &((k_heapk_node_t *)p)[-1];
        if (memk_node->key_size == 0)
        {
            return NULL;
        }
        else
        {
            return &((uint8_t *)&memk_node[1])[(memk_node->mem_size + sizeof(int) - 1) / sizeof(int) * sizeof(int)];
        }
    }
}

/**
 * @brief 通过内存封装地址获取 heapk_malloc() 申请时设定的键值的有效字节数
 *
 * @param p 已申请的内存地址
 * @return uint8_t 键值的有效字节数
 */
uint8_t heapk_key_size(void *p)
{
    if (_heapk_valid_state(p) == false)
    {
        return 0;
    }
    else
    {
        k_heapk_node_t *memk_node = &((k_heapk_node_t *)p)[-1];
        return memk_node->key_size;
    }
}
